/*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: GPL-2.0-only
 */

#pragma once

#include <config.h>
#include <types.h>
#include <object/structures.h>
#include <object/tcb.h>
#include <mode/types.h>

#ifdef ENABLE_SMP_SUPPORT
#define NODE_STATE_BEGIN(_name)                 typedef struct _name {  /*Z 开始一个struct定义 */
#define NODE_STATE_END(_name)                   } _name ## _t           /*Z 结束一个struct定义 */
#define NODE_STATE_TYPE_DECLARE(_name, _state)  _name ## _t _state
#define NODE_STATE_DECLARE(_type, _state)       _type _state

#define SMP_STATE_DEFINE(_type, _state)         _type _state
#define UP_STATE_DEFINE(_type, _state)

#define SMP_COND_STATEMENT(_st)                 _st     /*Z 对SMP用该值，对UP为空 */
#define SMP_TERNARY(_smp, _up)                  _smp    /*Z 对SMP用前值，对UP用后值 */

#define MODE_NODE_STATE_ON_CORE(_state, _core)  ksSMP[(_core)].cpu.mode._state  /*Z 当前cpu的CR3 */
#define ARCH_NODE_STATE_ON_CORE(_state, _core)  ksSMP[(_core)].cpu._state       /*Z 当前cpu的处理器重要寄存器、中断状态 */
#define NODE_STATE_ON_CORE(_state, _core)       ksSMP[(_core)].system._state    /*Z 当前cpu的系统运行状态信息 */

#define CURRENT_CPU_INDEX() getCurrentCPUIndex()    /*Z 获取当前cpu索引 */

#else

#define NODE_STATE_BEGIN(_name)
#define NODE_STATE_END(_name)
#define NODE_STATE_TYPE_DECLARE(_name, _state)
/* UP states are declared as VISIBLE so that they are accessible in assembly */
#define NODE_STATE_DECLARE(_type, _state)       extern _type _state VISIBLE /*Z 声明类型_type的变量_state */

#define SMP_STATE_DEFINE(_name, _state)
#define UP_STATE_DEFINE(_type, _state)          _type _state

#define SMP_COND_STATEMENT(_st)
#define SMP_TERNARY(_smp, _up)                  _up

#define MODE_NODE_STATE_ON_CORE(_state, _core) _state
#define ARCH_NODE_STATE_ON_CORE(_state, _core) _state
#define NODE_STATE_ON_CORE(_state, _core)      _state

#define CURRENT_CPU_INDEX() 0

#endif /* ENABLE_SMP_SUPPORT */

#define NUM_READY_QUEUES (CONFIG_NUM_DOMAINS * CONFIG_NUM_PRIORITIES)       /*Z 每个CPU的调度队列数量：域 X 优先级 */
#define L2_BITMAP_SIZE ((CONFIG_NUM_PRIORITIES + wordBits - 1) / wordBits)  /*Z 优先级队列位图需要的字数。位图用于标识队列是否为空 */

NODE_STATE_BEGIN(nodeState)   /*Z per CPU线程运行有关状态 */
NODE_STATE_DECLARE(tcb_queue_t, ksReadyQueues[NUM_READY_QUEUES]);/*Z ready调度队列。每域的每个优先级一个 */
NODE_STATE_DECLARE(word_t, ksReadyQueuesL1Bitmap[CONFIG_NUM_DOMAINS]);/*Z ready队列一级位图，指示二级位图的字是否有非空队列。低优先级在右：第0位表示第4个字 */
NODE_STATE_DECLARE(word_t, ksReadyQueuesL2Bitmap[CONFIG_NUM_DOMAINS][L2_BITMAP_SIZE]);/*Z ready队列二级位图，指示每优先级队列是否非空。高优先级在前：第0个字的63位代表优先级255队列 */
NODE_STATE_DECLARE(tcb_t, *ksCurThread);/*Z 正运行或准备运行的线程(已从ready队列中摘出) */
NODE_STATE_DECLARE(tcb_t, *ksIdleThread);/*Z idle线程TCB指针 */
NODE_STATE_DECLARE(tcb_t, *ksSchedulerAction);/*Z 调度器要调度的线程或要做的特殊动作(共2个) */

#ifdef CONFIG_KERNEL_MCS
NODE_STATE_DECLARE(tcb_t, *ksReleaseHead);/*Z 等待充值的线程双向链表头。按线程头refill单元的预算启用时间升序排序 */
NODE_STATE_DECLARE(time_t, ksConsumed);/*Z 已消费时间(进入内核时时累加，线程切换时归零) */
NODE_STATE_DECLARE(time_t, ksCurTime);/*Z 当前TSC计数值(进入内核时更新) */
NODE_STATE_DECLARE(bool_t, ksReprogram);/*Z 是否需要重设调度定时器 */
NODE_STATE_DECLARE(sched_context_t, *ksCurSC);/*Z 当前调度上下文 */
#endif

#ifdef CONFIG_HAVE_FPU
/* Current state installed in the FPU, or NULL if the FPU is currently invalid */
NODE_STATE_DECLARE(user_fpu_state_t *, ksActiveFPUState);/*Z 活跃FPU状态指针 */
/* Number of times we have restored a user context with an active FPU without switching it */
NODE_STATE_DECLARE(word_t, ksFPURestoresSinceSwitch);/*Z 切换至当前属主后使能/禁用FPU的次数 */
#endif /* CONFIG_HAVE_FPU */
#ifdef CONFIG_DEBUG_BUILD
NODE_STATE_DECLARE(tcb_t *, ksDebugTCBs);/*Z 当前处于DEBUG状态的TCB */
#endif /* CONFIG_DEBUG_BUILD */
#ifdef CONFIG_BENCHMARK_TRACK_UTILISATION
NODE_STATE_DECLARE(bool_t, benchmark_log_utilisation_enabled);
NODE_STATE_DECLARE(timestamp_t, benchmark_start_time);
NODE_STATE_DECLARE(timestamp_t, benchmark_end_time);
NODE_STATE_DECLARE(timestamp_t, benchmark_kernel_time);
NODE_STATE_DECLARE(timestamp_t, benchmark_kernel_number_entries);
NODE_STATE_DECLARE(timestamp_t, benchmark_kernel_number_schedules);
#endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */

NODE_STATE_END(nodeState);
extern word_t ksNumCPUs;

#if defined ENABLE_SMP_SUPPORT && defined CONFIG_ARCH_ARM
#define INT_STATE_ARRAY_SIZE ((CONFIG_MAX_NUM_NODES - 1) * NUM_PPI + maxIRQ + 1)
#else
#define INT_STATE_ARRAY_SIZE (maxIRQ + 1)   /*Z 128。硬件中断数量上限 */
#endif
extern word_t ksWorkUnitsCompleted;
extern irq_state_t intStateIRQTable[];
extern cte_t intStateIRQNode[];/*Z IRQ的CNode。由用户空间实现，其能力是通知能力，指向中断处理线程 */

extern const dschedule_t ksDomSchedule[];
extern const word_t ksDomScheduleLength;
extern word_t ksDomScheduleIdx;
extern dom_t ksCurDomain;
#ifdef CONFIG_KERNEL_MCS
extern ticks_t ksDomainTime;
#else
extern word_t ksDomainTime;
#endif
extern word_t tlbLockCount VISIBLE;
/*Z 每cpu的idle线程TCB */
extern char ksIdleThreadTCB[CONFIG_MAX_NUM_NODES][BIT(seL4_TCBBits)];

#ifdef CONFIG_KERNEL_MCS
extern char ksIdleThreadSC[CONFIG_MAX_NUM_NODES][BIT(seL4_MinSchedContextBits)];/*Z 每cpu的idle线程调度上下文 */
#endif

#ifdef CONFIG_BENCHMARK_USE_KERNEL_LOG_BUFFER
extern paddr_t ksUserLogBuffer;
#endif /* CONFIG_BENCHMARK_USE_KERNEL_LOG_BUFFER */

#define SchedulerAction_ResumeCurrentThread ((tcb_t*)0) /*Z 用特殊的tcb_t指针0值表示最终决策是ksCurThread所指 */
#define SchedulerAction_ChooseNewThread ((tcb_t*) 1)    /*Z 用特殊的tcb_t指针1值表示需要选择新的线程 */

#define MODE_NODE_STATE(_state)    MODE_NODE_STATE_ON_CORE(_state, getCurrentCPUIndex())/*Z 当前cpu的CR3 */
#define ARCH_NODE_STATE(_state)    ARCH_NODE_STATE_ON_CORE(_state, getCurrentCPUIndex())/*Z 当前cpu的处理器重要寄存器、中断状态 */
#define NODE_STATE(_state)         NODE_STATE_ON_CORE(_state, getCurrentCPUIndex())     /*Z 当前cpu的系统运行状态信息 */

